package com.osilon.util;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Logger;


import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;

import com.osilon.asm.OsilonClassNode;

public class ClassCache {
	private Logger logger = Logger.getLogger("Osilion");
	private JarFile jar;
	private Map<String, OsilonClassNode> classes = new HashMap<String, OsilonClassNode>();
	
	public ClassCache(JarFile jar) {
		this.jar = jar;
		loadClasses();
	}
	
	private void loadClasses() {
		Enumeration<JarEntry> entries = jar.entries();
		
		while(entries.hasMoreElements()) {
			JarEntry entry = entries.nextElement();
			
			if(entry.getName().endsWith(".class")) {
				try {
					OsilonClassNode node = new OsilonClassNode();
					ClassReader reader = new ClassReader(jar.getInputStream(entry));
					reader.accept(node, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
					
					classes.put(node.name, node);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		logger.info("Loaded " + classes.size() + " classes into memory.");
	}
	
	public boolean contains(String name) {
		return classes.get(name.replace('.', '/')) != null;
	}
	
	public byte[] getCode(String name) {
		if(contains(name)) {
			ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
			classes.get(name.replace('.', '/')).accept(writer);
			return writer.toByteArray();
		} 
		
		return null;
	}
	
	public OsilonClassNode getClass(String name) {
		return classes.get(name);
	}
	
	public OsilonClassNode[] getClasses() {
		return classes.values().toArray(new OsilonClassNode[0]);
	}
}
